/*
   FieldVis - A Tool for Visualizing Astrophysical Magnetohydrodynamic Flow
   
   Copyright (C) 2006 - 2008     FieldVis Development Team
  
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
  
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
  
   You should have received a copy of the GNU General Public License along
   with this program; if not, write to the Free Software Foundation, Inc.,
   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
   File     : Point.cpp
   Author   : Blayne Field
   
   Purpose  : Implementation file for the Point class.
              This class just holds a 3D point.
*/

#include <iostream>
#include <fstream>
#include <cmath>
#include <vector>
#include "Point.h"
#include "Vector3D.h"


float Point::DistanceBetween(Point p0, Point p1)
{
   float dx = p0.x - p1.x;
   float dy = p0.y - p1.y;
   float dz = p0.z - p1.z;
   return sqrt(dx*dx + dy*dy + dz*dz);
}

// returns an vector of points from the given file
std::vector<Point> Point::GetPointsFromFile(std::string fileName)
{
   // open up the file
   std::ifstream in(fileName.c_str());
   std::vector<Point> points;

   Point point;
   float x, y, z;
   while (!in.eof())
   {
      in >> x >> y >> z;
      point = Point(x, y, z);
      
      // need to check for eof here again to not insert a duplicate point into
      // the container when we read the end of the seed point file.
      if (!in.eof())
         points.push_back(point);
   }

   in.close();
   return points;
}

// moves the point 'dist' distance in the given direction
void Point::AddVector3D(Vector3D vec, float dist = 1)
{
   x += (vec.GetX() * dist);
   y += (vec.GetY() * dist);
   z += (vec.GetZ() * dist);
}

Point Point::operator+(Vector3D vecToAdd)
{
   Point temp(x + vecToAdd.GetX(), 
              y + vecToAdd.GetY(),
              z + vecToAdd.GetZ());
   return temp;
}

Point Point::operator*(float factor)
{
   Point temp(x * factor,
              y * factor,
              z * factor);
   return temp;
}

bool Point::operator==(const Point & compareTo) const
{
   return((x == compareTo.x) && (y == compareTo.y) && (z == compareTo.z));
}

Vector3D Point::VectorFromTo(Point p0, Point p1)
{
   Vector3D vec(p1.x - p0.x, p1.y - p0.y, p1.z - p0.z);
   return vec;
}

Point & Point::operator=(const Point & toCopy)
{
   if (this != &toCopy)
   {
      x = toCopy.x;
      y = toCopy.y;
      z = toCopy.z;
   }

   return *this;
}

std::ostream & operator<<(std::ostream & out, Point & p)
{
   out << p.GetX() << " " << p.GetY() << " " << p.GetZ() << std::endl;
   return out;
}

